﻿#include "guild_repository_logic.h"

#include "GuildRepoCell_struct.h"
#include "GuildAuctionRole_struct.h"
#include "GuildAuctionRoleInfo_struct.h"
#include "GuildAuctionAttentionInfo_struct.h"
#include "GuildAuctionItem_struct.h"
#include "GuildModuleRepository_struct.h"

#include "GuildMember_struct.h"
#include "GuildModuleMembers_struct.h"

#include "error/make_error_code.h"
#include "guild/module/guild_module_loader.hpp"
#include "guild/module/guild_module_saver.hpp"
#include "guild/guild_loader.hpp"

#include "util/time_util.hh"

namespace guild_service {
bool GuildModuleRepositoryLogic::GetModuleRepository(
    const guild_id_type guild_id, GuildModuleRepository &module_repository) {
  return detail::GetGuildModule<GuildModuleRepository>(
      kGuildServiceWelfareName, guild_id, kGuildModuleRepositoryName,
      module_repository);
}

bool GuildModuleRepositoryLogic::SetGuildAuctionOffer(
    const role_uuid_type role_uuid, const uint64_t item_uuid,
    const uint32_t offer, uint32_t &old_offer, error_code &ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid, guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleRepository module_repository;
  if (!GuildModuleRepositoryLogic::GetModuleRepository(guild_id, module_repository)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_LOAD_FAILED;
    return false;
  }

  auto &auction_map = module_repository.auction_map;
  auto it = auction_map.find(item_uuid);
  if (it == auction_map.end()) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_ITEM_NOT_EXIST;
    return false;
  }

  auto &role_info = it->second.role_info;
  {
    old_offer = role_info.role_map[role_uuid].offer;
    role_info.role_map[role_uuid].offer = offer;

    if (offer > role_info.max_offer) {
      role_info.max_offer = offer;
      role_info.max_offer_role_uuid = role_uuid;
    }
  }

  return detail::SaveGuildModule<GuildModuleRepository>(
      kGuildServiceWelfareName, module_repository, guild_id,
      kGuildModuleRepositoryName);
}

bool GuildModuleRepositoryLogic::SetGuildAuctionAttention(
    const role_uuid_type role_uuid, const uint64_t item_uuid, bool is_attention,
    error_code &ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid, guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleRepository module_repository;
  if (!GuildModuleRepositoryLogic::GetModuleRepository(guild_id, module_repository)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_LOAD_FAILED;
    return false;
  }

  auto &auction_map = module_repository.auction_map;
  auto it = auction_map.find(item_uuid);
  if (it == auction_map.end()) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_ITEM_NOT_EXIST;
    return false;
  }

  bool result = false;
  if (is_attention) {
    result = it->second.attention_info.role_set.emplace(role_uuid).second;
  } else {
    result = it->second.attention_info.role_set.erase(role_uuid) > 0;
  }

  if (!result) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_ATTENTION_FAILED;
    return false;
  }

  if (!detail::SaveGuildModule<GuildModuleRepository>(
      kGuildServiceWelfareName, module_repository, guild_id,
      kGuildModuleRepositoryName)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildModuleRepositoryLogic::AddGuildRepositoryCellItem(
    const role_uuid_type role_uuid, const uint32_t item_id, error_code &ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid, guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleRepository module_repository;
  if (!GuildModuleRepositoryLogic::GetModuleRepository(guild_id, module_repository)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_LOAD_FAILED;
    return false;
  }

  GuildRepoCell cell;
  if (!detail::IncrGuildGeneralId(kGuildServiceWelfareName, detail::kItemSeqKey, cell.item_uuid)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_GEN_ITEM_UUID_FAILED;
    return false;
  }
  cell.item_id = item_id;
  cell.create_timestamp = kratos::util::get_os_time_millionsecond();

  auto &cell_map = module_repository.cell_map;
  if (!cell_map.emplace(cell.item_uuid, cell).second) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_ADD_ITEM_FAILED;
    return false;
  }

  if (!detail::SaveGuildModule<GuildModuleRepository>(
          kGuildServiceWelfareName, module_repository, guild_id,
          kGuildModuleRepositoryName)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildModuleRepositoryLogic::DelGuildRepositoryCellItem(
    const role_uuid_type role_uuid, const uint64_t item_uuid, error_code &ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid,
                                 guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }
  if (!GuildModuleRepositoryLogic::CheckMemberDuty(
          role_uuid, guild_id,
          std::vector<duty_type>{duty_type::GUILD_DUTY_CHAIRMAN,
                                 duty_type::GUILD_DUTY_VICE_CHAIRMAN})) {
    ec = ErrorCode::ERR_GUILD_MEMBERS_DUTY_PERMISSION_DENIED;
    return false;
  }

  GuildModuleRepository module_repository;
  if (!GuildModuleRepositoryLogic::GetModuleRepository(guild_id,
                                                       module_repository)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_LOAD_FAILED;
    return false;
  }

  auto &cell_map = module_repository.cell_map;
  if (!cell_map.erase(item_uuid) == 0) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_DEL_ITEM_FAILED;
    return false;
  }

  if (!detail::SaveGuildModule<GuildModuleRepository>(
          kGuildServiceWelfareName, module_repository, guild_id,
          kGuildModuleRepositoryName)) {
    ec = ErrorCode::ERR_GUILD_MOD_REPOSITORY_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildModuleRepositoryLogic::CheckMemberDuty(
    const role_uuid_type role_uuid, const guild_id_type guild_id,
    const std::vector<duty_type> &duty_list) {
  if (role_uuid == kInvalidRoleUuid
    || guild_id == kInvalidGuildId) {
    return false;
  }

  if (duty_list.empty()) {
    return false;
  }

  GuildModuleMembers module_member;
  if (!detail::GetGuildModule<GuildModuleMembers>(kGuildServiceWelfareName, guild_id,
                                            kGuildModuleMembersName, module_member)) {
    return false;
  }

  for (const auto &it: module_member.members) {
    if (it.role_uuid == role_uuid) {
      for (const auto &it_duty: duty_list) {
        if (it.duty == it_duty) {
          return true;
        }
      }
      return false;
    }
  }

  return true;
}

}  // namespace guild_service
